// pages/promise/all-any-more/all-any-more.js

// https://blog.csdn.net/weixin_64684095/article/details/139576622
// 前端 JS 经典：Promise 详解
Page({

  /**
   * 页面的初始数据
   */
  data: {

  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {

  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  promiseAll() {
    // 启动一个耗时任务并用promise管理
    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('耗时1成功')
        console.log(new Date(), '耗时1成功')
      }, 1000);
    })
    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('耗时2成功')
        console.log(new Date(), '耗时2成功')
      }, 2000);
    })
    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject('耗时3失败')
        console.log(new Date(), '耗时3失败')
      }, 3000);
    })

    Promise.all([p1, p2, p3]).then((success) => {
      console.log(new Date(), 'promiseAll 都成功', success)
    }).catch((fail) => {
      console.log(new Date(), 'promiseAll 有失败', fail)
    }).finally(() => {
      console.log(new Date(), 'promiseAll 都结束')
    })
  },
  promiseAllSettle() {
    // https://blog.csdn.net/weixin_64684095/article/details/139576622
    // 所有执行都有结果了就执行，无论成功还是失败
    Promise.allSettled([
      this.loadingData('加载1', 1000),
      this.loadingData('加载2', 2000),
      this.loadingData('加载3', 3000),
      this.loadingData('加载4', 4000),
    ]).then((res) => {
      console.log(new Date(), 'allSettled 结果都返回', (typeof res), res[0], res)
    })
  },

  loadingData(msg, delay) {
    return new Promise((resolve, reject) => {
      console.log(new Date(), `耗时任务${msg}--开始`)
      setTimeout(() => {
        if (msg.indexOf(4) == -1) {
          resolve(msg + '完成')
          console.log(new Date(), `耗时任务${msg}-----完成`)
        } else {
          reject(msg + '失败')
          console.log(new Date(), `耗时任务${msg}-----失败`)
        }
      }, delay);
    })
  },

  promiseAny() {
    Promise.any([
      this.loadingData('任务1', 3000),
      this.loadingData('任务2', 2000),
      this.loadingData('任务4', 1000),
    ]).then((res) => {
      console.log(new Date(), 'any 任意异步成功就执行 ', (typeof res), res[0], res) //  "string" "任" "任务2完成",string也能直接通过下标回去字符
      // throw 'any An error111' 这里抛出异常也不影响其他(更久的)异步任务
    })
  },

  promiseRace() {
    Promise.race([
      this.loadingData('任务1', 3000),
      this.loadingData('任务2', 2000),
      this.loadingData('任务4', 1000),
    ]).then((res) => {
      console.log(new Date(), 'any then 任意异步(成功或者失败)返回就执行 ', (typeof res), res[0], res)
      // reject先走用catch接收，否则抛出异常
    }).catch((res) => {
      console.log(new Date(), 'any catch 任意异步(成功或者失败)返回就执行 ', (typeof res), res[0], res)
    })
  },

  promiseReject() {
    console.log(new Date(), 'promiseReject 111')
    let p = this.testReject()
    p.then((res) => {
      console.log(new Date(), 'promiseReject then', res)
    }).catch((fail) => {
      // Promise.reject('503失败') 抛出异常，.catch抓取不到
      console.log(new Date(), 'promiseReject catch', fail)
    })
    console.log(new Date(), 'promiseReject 222', p)
  },

  async testReject() {
    await setTimeout(() => {
      // 这是异步的return需要用 async + await。否则默认返回的是undefined。 Cannot read property 'then' of undefined
      return Promise.reject('503失败') // 返回一个状态为 rejected 的 Promise 对象
    }, 2000);
  },

  /**
   * 会接收 4 种类型的参数：promise 实例 、具有 then 方法的对象、没有 then 方法的对象、不传参
   */
  promiseResolve() {
    // ①当入参数是一个 Promise 实例时，直接返回这个实例。
    console.log(new Date(), "promiseResolve 111", Promise.resolve(this.loadingData('耗时4', 1000)))
    console.log(new Date(), "promiseResolve 111-222", JSON.stringify(Promise.resolve(this.loadingData('耗时3', 1000)))) // 可以比较得出log会log出异步的结果，即log不是实时当前，要留意比如定义了一个let在异步变化了，log可能会异步后的数据
    // ②当入参是一个具有 then 方法的对象时，将这个对象转为 Promise 对象，并立即执行对象的 then 方法
    let obj = {
      name:'hahaha',
      then(){
        console.log(new Date(),'对象里的then',this.name)
      }
    }
    console.log(new Date(),'promiseResolve 222',Promise.resolve(obj))

    // ③当入参是一个没有 then 方法的对象，或者参数不是对象时，就会返回状态为 fulfilled 的新的 Promise 对象，并将参数传入下一个 then
    // let phone = {
    //   brand:'huawei'
    // }

    let phone = 'xixi'
    let prso2 =  Promise.resolve(phone);
    prso2.then((then)=>{
      console.log(new Date(),'promiseResolve 333 prso2 then',then)
    })
    console.log(new Date(),'promiseResolve 333',prso2)
    // ④ 当不带任何参数时，就会返回一个状态为 fulfilled 的 Promise 对象
    console.log(new Date(),'promiseResolve 444',Promise.resolve())
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})